package org.gdstash.ui;

import org.gdstash.db.DBAffix;
import org.gdstash.db.DBItem;
import org.gdstash.db.DBStat;
import org.gdstash.db.SelectionCriteria;
import org.gdstash.item.GDItem;
import org.gdstash.ui.stash.GDSharedStashPane;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.ui.util.GDCharInfoList;
import org.gdstash.ui.util.GDStashInfoList;
import org.gdstash.util.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class GDCraftPane extends AdjustablePanel implements GDUITransfer, GDUISearch, GDUIFilter {
    private GDStashFrame frame;
    private GDSharedStashPane pnlStash;
    private JButton btnFilter;
    private GDItemCraftPane pnlCraft;
    private JButton btnReload;
    private JButton btnHelp;
    private JButton btnFileSave;
    private GDItemNameTablePane pnlTable;
    private JButton btnSearch;
    private GDStashInfoList.GDStashFileInfo info;
    private GDItem selItem;
    private int location;
    private JPanel pnlMain;
    private GDTabbedSearchDialog dlgSearch;
    private GDFilterDialog dlgFilter;
    private SelectionCriteria criteria;

    public GDCraftPane(final GDStashInfoList.GDStashFileInfo info, final GDStashFrame frame) {
        this.info = info;
        this.frame = frame;
        this.selItem = null;
        this.location = 0;
        this.dlgSearch = null;
        this.dlgFilter = null;
        this.adjustUI();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        this.pnlMain = this.buildMainPanel();
        final JScrollPane scroll = new JScrollPane(this.pnlMain);
        scroll.getVerticalScrollBar().setUnitIncrement(2 * GDStashFrame.iniConfig.sectUI.fontSize);
        layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(scroll));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(scroll));
        layout.setVerticalGroup(vGroup);
    }

    @Override
    public void adjustUI() {
        Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntButton = UIManager.getDefaults().getFont("Button.font");
        if (fntButton == null) {
            fntButton = fntLabel;
        }
        Font fntCombo = UIManager.getDefaults().getFont("ComboBox.font");
        if (fntCombo == null) {
            fntCombo = fntLabel;
        }
        Font fntTabbed = UIManager.getDefaults().getFont("TabbedPane.font");
        if (fntTabbed == null) {
            fntTabbed = fntLabel;
        }
        fntLabel = fntLabel.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntButton = fntButton.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntCombo = fntCombo.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntTabbed = fntTabbed.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        if (this.btnSearch == null) {
            (this.btnSearch = new JButton()).addActionListener(new SearchItemsListener());
        }
        this.btnSearch.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_SEARCH"));
        this.btnSearch.setIcon(GDImagePool.iconBtnSearch24);
        this.btnSearch.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnSearch, "MNC_SEARCH_SECOND");
        if (this.btnFilter == null) {
            (this.btnFilter = new JButton()).addActionListener(new FilterAffixListener());
            this.btnFilter.setEnabled(false);
        }
        this.btnFilter.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_FILTER"));
        this.btnFilter.setIcon(GDImagePool.iconBtnFilter24);
        this.btnFilter.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnFilter, "MNC_FILTER");
        if (this.btnFileSave == null) {
            (this.btnFileSave = new JButton()).setEnabled(false);
            this.btnFileSave.addActionListener(new FileSaveActionListener());
        }
        this.btnFileSave.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_STASH_SAVE"));
        this.btnFileSave.setIcon(GDImagePool.iconBtnSave24);
        this.btnFileSave.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnFileSave, "MNC_STASH_SAVE");
        if (this.btnReload == null) {
            (this.btnReload = new JButton()).addActionListener(new StashReloadActionListener());
        }
        this.btnReload.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_RELOAD"));
        this.btnReload.setIcon(GDImagePool.iconBtnReload24);
        this.btnReload.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnReload, "MNC_RELOAD");
        if (this.btnHelp == null) {
            (this.btnHelp = new JButton()).addActionListener(new GDHelpActionListener("05_craft.html"));
        }
        this.btnHelp.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_HELP"));
        this.btnHelp.setIcon(GDImagePool.iconBtnQuestion24);
        this.btnHelp.setFont(fntButton);
        GDStashFrame.setMnemonic(this.btnHelp, "MNC_HELP");
        if (this.pnlCraft == null) {
            this.pnlCraft = new GDItemCraftPane();
        } else {
            this.pnlCraft.adjustUI();
        }
        if (this.pnlTable == null) {
            (this.pnlTable = new GDItemNameTablePane((List<GDItem>) null, true)).addActionListener(new TableActionListener());
            this.pnlTable.setMinimumSize(new Dimension(300, 200));
            this.pnlTable.setMaximumSize(new Dimension(600, 2000));
        } else {
            this.pnlTable.adjustUI();
        }
        if (this.pnlStash == null) {
            this.pnlStash = new GDSharedStashPane(this.info, 2, this.frame, this);
        } else {
            this.pnlStash.adjustUI();
        }
        if (this.dlgSearch != null) {
            this.dlgSearch.adjustUI();
        }
        if (this.dlgFilter != null) {
            this.dlgFilter.adjustUI();
        }
    }

    @Override
    public void updateUI() {
        super.updateUI();
        if (this.dlgSearch != null) {
            SwingUtilities.updateComponentTreeUI(this.dlgSearch);
        }
        if (this.dlgFilter != null) {
            SwingUtilities.updateComponentTreeUI(this.dlgFilter);
        }
    }

    public void refresh() {
        if (this.pnlTable != null) {
            this.pnlTable.refresh();
        }
        if (this.pnlCraft != null) {
            this.pnlCraft.refresh();
        }
    }

    private JPanel buildMainPanel() {
        final JPanel panel = new JPanel();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel pnlTable = this.buildTablePanel();
        final JPanel pnlItemInfo = this.buildInfoPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(pnlTable)).addGroup(layout.createParallelGroup().addComponent(pnlItemInfo)).addGroup(layout.createParallelGroup().addComponent(this.pnlStash));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.pnlStash).addComponent(pnlItemInfo).addComponent(pnlTable));
        layout.setVerticalGroup(vGroup);
        return panel;
    }

    private JPanel buildTablePanel() {
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = new JPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.btnSearch).addComponent(this.pnlTable));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.btnSearch)).addGroup(layout.createParallelGroup().addComponent(this.pnlTable));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.btnSearch, this.pnlTable);
        return panel;
    }

    private JPanel buildInfoPanel() {
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = new JPanel();
        final JPanel pnlButtonFile = this.buildFileButtonPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(pnlButtonFile).addComponent(this.btnFilter).addComponent(this.pnlCraft));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(pnlButtonFile)).addGroup(layout.createParallelGroup().addComponent(this.btnFilter)).addGroup(layout.createParallelGroup().addComponent(this.pnlCraft));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, pnlButtonFile, this.btnFilter);
        layout.linkSize(0, pnlButtonFile, this.pnlCraft);
        return panel;
    }

    private JPanel buildFileButtonPanel() {
        final BorderLayout layout = new BorderLayout();
        final JPanel panel = new JPanel();
        panel.setLayout(layout);
        panel.add(this.btnFileSave, "Center");
        panel.add(this.btnReload, "West");
        panel.add(this.btnHelp, "East");
        int size = 12;
        if (GDStashFrame.iniConfig != null) {
            size = GDStashFrame.iniConfig.sectUI.fontSize;
        }
        final Dimension dimPref = new Dimension(30 * size, 2 * size);
        final Dimension dimMax = new Dimension(50 * size, 2 * size);
        panel.setPreferredSize(dimPref);
        panel.setMaximumSize(dimMax);
        return panel;
    }

    public void updateStash() {
        this.pnlStash.layoutStash();
        this.pnlStash.updateModSelection();
    }

    public void updateConfig() {
        if (this.dlgSearch != null) {
            this.dlgSearch.updateConfig();
        }
    }

    public void refreshStashSelection() {
        this.pnlStash.refreshStashSelection();
    }

    public void setStashInfo(final GDStashInfoList.GDStashFileInfo info) {
        this.info = info;
        if (this.pnlStash != null) {
            this.pnlStash.setStash(info);
        }
    }

    public void refreshStashInfo(final GDStashInfoList.GDStashFileInfo info) {
        if (info == null) {
            return;
        }
        if (this.info == null) {
            return;
        }
        if (this.info.fileName.equals(info.fileName)) {
            this.info = info;
            if (this.pnlStash != null) {
                this.pnlStash.setStash(info);
            }
        }
    }

    public boolean updateStashFile() {
        if (this.info == null) {
            return false;
        }
        if (this.info.gdStash == null) {
            return false;
        }
        if (GDStashFrame.iniConfig == null) {
            return false;
        }
        if (GDStashFrame.iniConfig.sectDir.savePath == null) {
            return false;
        }
        try {
            String stashMod = this.info.gdStash.getModName();
            if (stashMod == null) {
                stashMod = "";
            }
            String dir = this.info.gdStash.getFile().getParentFile().getCanonicalPath();
            if (dir.length() > GDStashFrame.iniConfig.sectDir.savePath.length()) {
                dir = dir.substring(GDStashFrame.iniConfig.sectDir.savePath.length() + 1);
            } else {
                dir = "";
            }
            if (stashMod.equals(dir)) {
                return false;
            }
            dir = GDStashFrame.iniConfig.sectDir.savePath;
            if (!dir.endsWith(GDConstants.FILE_SEPARATOR)) {
                dir += GDConstants.FILE_SEPARATOR;
            }
            if (!stashMod.equals("")) {
                dir = dir + stashMod + GDConstants.FILE_SEPARATOR;
            }
            if (this.info.gdStash.isHardcore()) {
                dir += "transfer.gsh";
            } else {
                dir += "transfer.gst";
            }
            final File file = new File(dir);
            this.info.gdStash.setFile(file);
            return true;
        } catch (IOException ex) {
            return false;
        }
    }

    @Override
    public void setChar(final GDCharInfoList.GDCharFileInfo info) {
    }

    @Override
    public void setStash(final GDStashInfoList.GDStashFileInfo info) {
        if (this.info == info) {
            return;
        }
        this.info = info;
        this.checkSaveButton();
    }

    @Override
    public int getItemLocation() {
        return this.location;
    }

    @Override
    public GDItem getSelectedItem() {
        return this.selItem;
    }

    @Override
    public void setSelectedItem(final GDItem item, final int location) {
        if (location == 1) {
            this.pnlTable.clearSelection();
        }
        this.selItem = item;
        this.location = location;
        this.pnlCraft.setItem(item, location);
        this.btnFilter.setEnabled(item != null);
        if (this.pnlCraft.getPrefixes().isEmpty() && this.pnlCraft.getSuffixes().isEmpty()) {
            this.btnFilter.setEnabled(false);
        } else if (item != null && !item.isUnique() && this.criteria != null && !this.criteria.isInitial()) {
            this.filter(this.criteria);
        }
    }

    @Override
    public void transferSelectedItem(final int action, final int x, final int y) {
        switch (action) {
            case 1: {
                if (this.location == 1) {
                    final GDItem item = this.pnlStash.getSelectedItem();
                    if (item != null) {
                        this.pnlStash.moveSelectedItem(1, x, y);
                        this.btnFileSave.setEnabled(this.info.gdStash.hasChanged());
                    }
                    break;
                }
                break;
            }
            case 4: {
                if (this.location == 2) {
                    final GDItem clone = this.pnlCraft.getItem().clone();
                    final String s = this.pnlCraft.getSeed();
                    if (s == null) {
                        clone.createSeed();
                    } else {
                        clone.setSeedHex(s);
                    }
                    if (clone.isComponent()) {
                        clone.setVar1(clone.getDBItem().getComponentPieces());
                    }
                    final int i = this.pnlCraft.getCount();
                    if (i > 0) {
                        clone.setStackCount(i);
                    }
                    this.pnlStash.addItem(clone, 4, x, y);
                    this.btnFileSave.setEnabled(this.info.gdStash.hasChanged());
                    break;
                }
                break;
            }
        }
    }

    @Override
    public void checkSaveButton() {
        if (this.info == null) {
            this.btnFileSave.setEnabled(false);
        } else if (this.info.gdStash == null) {
            this.btnFileSave.setEnabled(false);
        } else {
            this.btnFileSave.setEnabled(this.info.gdStash.hasChanged());
        }
    }

    @Override
    public Frame getFrame() {
        return this.frame;
    }

    @Override
    public void search(final SelectionCriteria criteria) {
        this.pnlCraft.setItem(null, 0);
        final List<GDItem> items = new LinkedList<GDItem>();
        criteria.noEnemyOnly = true;
        final List<DBItem> dbItems = DBItem.getByCriteria(criteria);
        for (final DBItem dbi : dbItems) {
            if (criteria.combiMode == SelectionCriteria.CombinationMode.AND) {
                if (!DBStat.statsMeetCriteria(dbi.getStatList(), criteria)) {
                    continue;
                }
                if (criteria.dmgConversionFrom != null && !criteria.dmgConversionFrom.equals(dbi.getConvertIn())) {
                    continue;
                }
                if (criteria.dmgConversionTo != null && !criteria.dmgConversionTo.equals(dbi.getConvertOut())) {
                    continue;
                }
                if (criteria.petBonus && dbi.getPetBonusSkill() == null) {
                    continue;
                }
            }
            final GDItem item = new GDItem(dbi);
            items.add(item);
        }
        this.pnlTable.setItems(items);
        GDMsgLogger.showLog(this, GDMsgFormatter.getString(GDMsgFormatter.rbMsg, "ERR_SEARCH"));
    }

    @Override
    public void filter(final SelectionCriteria criteria) {
        this.criteria = criteria;
        if (criteria == null) {
            return;
        }
        final List<DBAffix> prefixes = this.pnlCraft.getPrefixes();
        final List<DBAffix> suffixes = this.pnlCraft.getSuffixes();
        final List<DBAffix> filterPrefixes = new LinkedList<DBAffix>();
        final List<DBAffix> filterSuffixes = new LinkedList<DBAffix>();
        for (final DBAffix affix : prefixes) {
            if (affix.matchesCriteria(criteria)) {
                filterPrefixes.add(affix);
            }
        }
        for (final DBAffix affix : suffixes) {
            if (affix.matchesCriteria(criteria)) {
                filterSuffixes.add(affix);
            }
        }
        this.pnlCraft.setFilteredPrefixes(filterPrefixes);
        this.pnlCraft.setFilteredSuffixes(filterSuffixes);
    }

    private class TableActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent ev) {
            final GDItem item = GDCraftPane.this.pnlTable.getSelectedItem();
            GDCraftPane.this.setSelectedItem(item, 2);
            GDMsgLogger.showLog(GDCraftPane.this, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERRORS"));
        }
    }

    private class StashReloadActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent ev) {
            if (GDCraftPane.this.info.gdStash != null && GDCraftPane.this.info.gdStash.hasChanged() && GDStashFrame.iniConfig.sectRestrict.dbStashMove) {
                final JButton[] buttons = {new JButton(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_YES"), GDImagePool.iconBtnOk24), new JButton(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_NO"), GDImagePool.iconBtnCancel24)};
                final String tag = "TXT_RELOAD_STASH";
                final int i = GDFlexDialog.showDialog(GDMsgFormatter.getString(GDMsgFormatter.rbUI, tag), buttons, 3, null, true);
                if (i == -1) {
                    return;
                }
                if (i == 1) {
                    return;
                }
            }
            GDStashInfoList.findStashes(GDCraftPane.this.frame, GDCraftPane.this.info, null);
            if (GDCraftPane.this.info != null) {
                for (final GDStashInfoList.GDStashFileInfo si : GDStashInfoList.gdStashFileInfos) {
                    if (si.fileName.equals(GDCraftPane.this.info.fileName)) {
                        GDCraftPane.this.info = si;
                        break;
                    }
                }
            }
            if (GDCraftPane.this.frame.pnlTransfer != null) {
                GDCraftPane.this.frame.pnlTransfer.refreshStashInfo(GDCraftPane.this.info);
            }
            if (GDCraftPane.this.frame.pnlCraft != null) {
                GDCraftPane.this.frame.pnlCraft.refreshStashInfo(GDCraftPane.this.info);
            }
            GDMsgLogger.showLog(GDCraftPane.this, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERRORS"));
        }
    }

    private class FileSaveActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent ev) {
            if (GDCraftPane.this.info == null) {
                return;
            }
            if (GDCraftPane.this.info.gdStash == null) {
                return;
            }
            if (GDCraftPane.this.frame.isCloudSaveDir() && GDStashFrame.isGrimDawnRunning()) {
                GDMsgLogger.addInfo(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "INFO_GD_CLOUD_SAVE"));
                GDMsgLogger.addInfo(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "INFO_GD_CLOSE"));
                GDMsgLogger.showLog(GDCraftPane.this.frame, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "INFO_GD_RUNNING"), GDLog.MessageType.Info, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "INFO_GD_RUNNING"));
                return;
            }
            boolean success = false;
            try {
                final boolean update = GDCraftPane.this.updateStashFile();
                GDCraftPane.this.info.gdStash.write();
                if (update) {
                    GDCraftPane.this.info.setFile(GDCraftPane.this.info.gdStash.getFile());
                    GDStashFrame.iniConfig.sectHistory.lastStash = GDCraftPane.this.info.fileName;
                    GDCraftPane.this.btnReload.doClick();
                }
                success = true;
            } catch (IOException ex) {
                GDMsgLogger.addError(ex);
            }
            if (success) {
                GDCraftPane.this.btnFileSave.setEnabled(GDCraftPane.this.info.gdStash.hasChanged());
            }
            GDMsgLogger.showLog(GDCraftPane.this, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "SUCC_STASH_SAVE"), GDLog.MessageType.Success, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERR_STASH_SAVE"));
        }
    }

    private class FilterAffixListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            if (GDCraftPane.this.dlgFilter == null) {
                GDCraftPane.this.dlgFilter = new GDFilterDialog(GDCraftPane.this.frame, GDCraftPane.this);
            }
            GDCraftPane.this.dlgFilter.setVisible(true);
        }
    }

    private class SearchItemsListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            if (GDCraftPane.this.dlgSearch == null) {
                GDCraftPane.this.dlgSearch = new GDTabbedSearchDialog(GDCraftPane.this.frame, GDCraftPane.this, GDTabbedSearchDialog.Mode.CRAFT, SelectionCriteria.SoulboundMode.ALL, false);
            }
            GDCraftPane.this.dlgSearch.setVisible(true);
        }
    }
}
